package org.apache.james.imap.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;

import org.apache.avalon.framework.logger.LogEnabled;
import org.apache.james.container.spring.logging.log4j.AvalonToLog4jLogger;
import org.apache.james.imapserver.ImapHandlerConfigurationData;
import org.apache.james.mailboxmanager.manager.MailboxManagerProvider;
import org.apache.james.services.UsersRepository;
import org.apache.log4j.Logger;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoAcceptor;
import org.apache.mina.common.SimpleByteBufferAllocator;
import org.apache.mina.filter.LoggingFilter;
import org.apache.mina.filter.SSLFilter;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.transport.socket.nio.SocketAcceptor;
import org.apache.mina.transport.socket.nio.SocketAcceptorConfig;

public class ImapServer {

	private IoAcceptor acceptor;

	int port = 10143;
	UsersRepository usersRepository;
	MailboxManagerProvider mmp;
	String helloName;
	
	SSLConfiguration sslConfiguration;
	
	boolean useSSL = false;
	
	
	public void setPort(int port) {
		this.port = port;
	}

	public void setUsersRepository(UsersRepository u) {
		this.usersRepository = u;
	}
	
    public void setMailboxManagerProvider(MailboxManagerProvider mmp) {
    	this.mmp = mmp;
    }
    
    public void setSslConfiguration(SSLConfiguration sslConfiguration) {
		this.sslConfiguration = sslConfiguration;
	}

    public void setHelloName(String helloName) {
		this.helloName = helloName;
	}
    
    
    public void setUseSSL(boolean useSSL) {
		this.useSSL = useSSL;
	}
    
	private class Config implements  ImapHandlerConfigurationData {
	
		public MailboxManagerProvider getMailboxManagerProvider() {
			return mmp;
		}
		
		public UsersRepository getUsersRepository() {
			return usersRepository;
		}
		
		public String getHelloName() {
			return helloName;
		}
		public int getResetLength() {
			return 10000; // ????
		}
	}
    


	
	public void init() throws IOException {
		 // The following two lines change the default buffer type to 'heap',
        // which yields better performance.
        ByteBuffer.setUseDirectBuffers(false);
        ByteBuffer.setAllocator(new SimpleByteBufferAllocator());

        acceptor = new SocketAcceptor();
        SocketAcceptorConfig cfg = new SocketAcceptorConfig();
        if (useSSL) {
        	if (sslConfiguration==null) {
        		throw new NullPointerException("SSLConfiguration is missing!");
        	}
        	try {
				cfg.getFilterChain().addFirst("ssl",
						new SSLFilter(sslConfiguration.getContext()));
			} catch (GeneralSecurityException e) {
				throw new RuntimeException("Security Problem setting up SSL:"
						+ e.getMessage(), e);
			}
        }
        cfg.getFilterChain().addLast( "logger", new LoggingFilter() );
        cfg.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new ImapCodecFactory( Charset.forName( "ISO-8859-1" ))));
        acceptor.bind( new InetSocketAddress(port), new ImapServerHandler(new Config()), cfg);
        System.out.println("ImapServer started at "+port+(useSSL ? " with SSL" : " without SSL"));
	}
	
	public static void main(String[] args) throws IOException {
		ImapServer imapServer = new ImapServer();
		imapServer.init();
	}
	
	
	public static void setupLog4jLogger(LogEnabled logEnabled) {
		if (logEnabled!=null) {
			AvalonToLog4jLogger avalonLogger = new AvalonToLog4jLogger(Logger.getLogger(logEnabled.getClass()));
			logEnabled.enableLogging(avalonLogger);
		}
	}
	
}
